/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.worsik.vypocty.topeni.tepelneztraty.model;

import cz.worsik.vypocty.topeni.tepelneztraty.service.VypoctyService;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author 231260
 */
public class Stena {
	private String nazev;
	private Boolean je_ochlazovana;
	private Integer teplota_za_kci;
	private Integer delka;
	private Integer vyska;
	private Integer tloustka;
	private Double soucinitel_k;
	private Mistnost mistnost;
	private SvetovaStrana svetovaStrana;
	
	private List<Otvor> otvoryList;
	
	private final Integer DEFAULT_TEPLOTA = 20;
	private final Integer DEFAULT_DELKA = 1000;
	private final Integer DEFAULT_VYSKA = 3000;
	private final Integer DEFAULT_TLOUSTKA = 300;
	private final Double DEFAULT_SOUCINITEL = 0d;
	private final Boolean DEFAULT_JE_OCHLAZOVANA = false;
	
	DecimalFormat format = new DecimalFormat("#000.##");

	public Stena(Mistnost mistnost) {
		format.setDecimalSeparatorAlwaysShown(false);
		this.otvoryList = new ArrayList<Otvor>();
		this.mistnost = mistnost;
	}

	public int getDelka() {
		if (delka == null)
			setDelka(DEFAULT_DELKA);
		return delka;
	}

	public void setDelka(Integer delka) {
		this.delka = delka;
	}

	public boolean isJe_ochlazovana() {
		if (je_ochlazovana == null)
			setJe_ochlazovana(DEFAULT_JE_OCHLAZOVANA);
		return je_ochlazovana;
	}

	public void setJe_ochlazovana(Boolean je_ochlazovana) {
		this.je_ochlazovana = je_ochlazovana;
		nastavVychoziSoucinitele();
	}

	public Mistnost getMistnost() {
		return mistnost;
	}

	public void setMistnost(Mistnost mistnost) {
		this.mistnost = mistnost;
	}

	public String getNazev() {
		return nazev;
	}

	public void setNazev(String nazev) {
		this.nazev = nazev;
	}
	
	public void setNazev(int i)
	{
		setNazev("S_"+format.format(i));
	}

	public double getSoucinitel_k() {
		if (soucinitel_k == null)
			return getDefault_K(isJe_ochlazovana());
		return soucinitel_k;
	}

	public void setSoucinitel_k(Double soucinitel_k) {
		this.soucinitel_k = soucinitel_k;
	}

	public SvetovaStrana getSvetovaStrana() {
		if (svetovaStrana == null)
			setSvetovaStrana(mistnost.getSvetova_strana());
		return svetovaStrana;
	}

	public void setSvetovaStrana(SvetovaStrana svetovaStrana) {
		this.svetovaStrana = svetovaStrana;
	}

	public int getTeplota_za_kci() {
		if (teplota_za_kci == null)
			return je_ochlazovana ? mistnost.getObjekt().getTeplota_venkovni() : DEFAULT_TEPLOTA;
		return teplota_za_kci;
	}

	public void setTeplota_za_kci(Integer teplota_za_kci) {
		this.teplota_za_kci = teplota_za_kci;
	}

	public int getTloustka() {
		if (tloustka == null)
			setTloustka(DEFAULT_TLOUSTKA);
		return tloustka;
	}

	public void setTloustka(Integer tloustka) {
		this.tloustka = tloustka;
	}

	public int getVyska() {
		if (vyska == null)
			setVyska(DEFAULT_VYSKA);
		return vyska;
	}

	public void setVyska(Integer vyska) {
		this.vyska = vyska;
	}

	public List<Otvor> getOtvoryList() {
		return otvoryList;
	}
	
	public void addOtvor(Otvor otvor)
	{
		otvoryList.add(otvor);
	}
	
	public void removeOtvor(int index)
	{
		if (index >= 0 && index < otvoryList.size())
			otvoryList.remove(index);
	}
	
	public void removeVsechnyOtvory()
	{
		otvoryList.clear();
	}
	
	public void nastavVychoziSoucinitelOtvoru(Otvor otvor)
	{
		VychoziHodnoty vychozi = mistnost.getObjekt().getVychoziHodnoty();
		
		if (otvor.isOkno())
		{
			otvor.setDefault_soucinitel_k(vychozi.getK_stena_okno());
			otvor.setDefault_soucinitel_i(vychozi.getI_okno());
		}
		else
		{
			otvor.setDefault_soucinitel_k((isJe_ochlazovana()) ? vychozi.getK_dvere_vnejsi() : vychozi.getK_dvere_vnitrni());
			otvor.setDefault_soucinitel_i((isJe_ochlazovana()) ? vychozi.getI_dvere() : 0d);
		}
	}
	
	public void nastavVychoziSoucinitele()
	{
		for (Otvor otvor : otvoryList)
		{
			nastavVychoziSoucinitelOtvoru(otvor);
		}
	}
	
	private Double getDefault_K(Boolean ochlazovana)
	{
		VychoziHodnoty vychozi = mistnost.getObjekt().getVychoziHodnoty();
		
		if (ochlazovana)
			return vychozi.getK_stena_vnejsi();
		else
			return vychozi.getK_stena_vnitrni();
	}
	
	public Object[] getRowData()
	{
		return new Object[] {
			// Název
			getNazev(),
			// Ochlazovana
			isJe_ochlazovana(),
			// Delka
			getDelka(),
			// Vyska
			getVyska(),
			// Tloustka
			getTloustka(),
			// Plocha
			getPlocha(),
			// Svetova Strana
			getSvetovaStrana(),
			// Soucinitel
			getSoucinitel_k(),
			// Teplota za kci
			getTeplota_za_kci(),
			// Poc. otvoru
			getPocetOtvoru(),
			// Plocha otvoru
			getPlochaOtvoru(),
			// Plocha bez otvoru
			getPlochaBezOtvoru(),
			// Tepelna ztrata
			getTepelnaZtrata()
			
			/*
		new SloupecTableModel("Název","Název",false,String.class,40),
		new SloupecTableModel("Och.","Je ochlazovaná",true,Boolean.class,40),
		new SloupecTableModel("Délka","Délka",true,Integer.class,50),
		new SloupecTableModel("Výška","Výška",true,Integer.class,50),
		new SloupecTableModel("Tloušťka","Tloušťka",true,Integer.class,50),
		new SloupecTableModel("Plocha","Plocha stěny",false,Double.class,60),
		new SloupecTableModel("Strana","Světová strana",true,SvetovaStrana.class,60),
		new SloupecTableModel("SPT","Součinitel prostupu tepla",true,Double.class,30),
		new SloupecTableModel("TZK","Teplota za konstrukcí",true,Integer.class,30),
		new SloupecTableModel("Otvory","Počet otvorů",false,Integer.class,40),
		new SloupecTableModel("Plocha","Plocha otvorů",false,Double.class,60),
		new SloupecTableModel("Bez otvorů","Plocha bez otvorů",false,Double.class,60),
		new SloupecTableModel("Tepelná ztráta","Tepelná ztráta",false,Double.class,80)
			 */
		};
	}

	public Double getPlocha() {
		Double delka_mm = new Double(getDelka())/1000d;
		Double vyska_mm = new Double(getVyska())/1000d;
		
		return delka_mm * vyska_mm;
	}

	private int getPocetOtvoru() {
		if (otvoryList == null)
			return 0;
		
		return otvoryList.size();
	}

	public Double getPlochaOtvoru() {
		if (otvoryList == null)
			return 0d;
		
		Double plocha = 0d;
		
		for (Otvor otvor : otvoryList)
		{
			plocha += otvor.getPlocha();
		}
		
		return plocha;
	}

	public Double getPlochaBezOtvoru() {
		return getPlocha() - getPlochaOtvoru();
	}

	public Double getTepelnaZtrata() {
		return VypoctyService.tepelnaZtrata(getPlochaBezOtvoru(),getSoucinitel_k(),mistnost.getTeplota_vnitrni(),getTeplota_za_kci());
	}
	
	private Double getTepelnaZtrataOtvoru() {
		if (otvoryList == null)
			return 0d;
		
		Double ztrata = 0d;
		
		for (Otvor otvor : otvoryList)
		{
			ztrata += otvor.getTepelnaZtrata(this);
		}
		
		return ztrata;
	}
	
	// TODO: upravit, pocita spatne
	public Double getTepelnaZtrataInfiltraci() {
		if (otvoryList == null)
			return 0d;
		
		Double ztrata = 0d;
		
		for (Otvor otvor : otvoryList)
		{
			ztrata += otvor.getTepelnaZtrata(this);
		}
		
		return ztrata;
	}
	
	public Double getTepelnaZtrataSOtvory() {
		return getTepelnaZtrata() + getTepelnaZtrataOtvoru();
	}
	
	public void setProperty(String metoda, Object hodnota, Class<?> trida)
	{
		if ("".equals(metoda))
			return;
		
		Method setter;
			
		try
		{
			setter = this.getClass().getDeclaredMethod(metoda, new Class[] {trida});
		}
		catch (NoSuchMethodException e)
		{
			setter = null;
		}
		
		if (setter != null)
		{
			try {
				setter.invoke(this, hodnota);
				
			} catch (IllegalAccessException ex) {
				Logger.getLogger(Stena.class.getName()).log(Level.SEVERE, null, ex);
			} catch (IllegalArgumentException ex) {
				Logger.getLogger(Stena.class.getName()).log(Level.SEVERE, null, ex);
			} catch (InvocationTargetException ex) {
				Logger.getLogger(Stena.class.getName()).log(Level.SEVERE, null, ex);
			}
		}
	}
}
